#ifndef __M_FMT_H__
#define __M_FMT_H__ 
#include "message.hpp"
#include <ctime>
#include <sstream>
#include <vector>
#include <cassert>

namespace qywlog
{
  // 抽象格式化子项基类
  class FormatItem
  {
    public:
      using ptr = std::shared_ptr<FormatItem>;
      virtual void format(std::ostream &out, const LogMsg &msg) = 0;
  };
  // 派生格式化子项子类 -- 消息，等级，时间，文件名，行号，线程ID，日志器名，制表符，换行，其他
  class MsgFormatItem : public FormatItem 
  {
    public:
      void format(std::ostream &out, const LogMsg &msg) override
      {
         out << msg._payload; 
      }
  };
  class LevelFormatItem : public FormatItem 
  {
    public:
      void format(std::ostream &out, const LogMsg &msg) override
      {
         out << LogLevel::toString(msg._level); 
      }
  };
  class TimeFormatItem : public FormatItem 
  {
    public:
      TimeFormatItem(const std::string &fmt = "%H:%M:%S")
        :_time_fmt(fmt)
        {}
      void format(std::ostream &out, const LogMsg &msg) override
      {
        struct tm t;
        localtime_r(&msg._ctime, &t);
        char tmp[32] = {0};
        strftime(tmp,31,_time_fmt.c_str(), &t);
         out << tmp; 
      }
    private:
      std::string _time_fmt;// %H:%M:%S
  };
  class FileFormatItem : public FormatItem 
  {
    public:
      void format(std::ostream &out, const LogMsg &msg) override
      {
         out << msg._file; 
      }
  };
  class LineFormatItem : public FormatItem 
  {
    public:
      void format(std::ostream &out, const LogMsg &msg) override
      {
         out << msg._line; 
      }
  };
  class ThreadFormatItem : public FormatItem 
  {
    public:
      void format(std::ostream &out, const LogMsg &msg) override
      {
         out << msg._tid; 
      }
  };
  class LoggerFormatItem : public FormatItem 
  {
    public:
      void format(std::ostream &out, const LogMsg &msg) override
      {
         out << msg._logger; 
      }
  };
  class TabFormatItem : public FormatItem 
  {
    public:
      void format(std::ostream &out, const LogMsg &msg) override
      {
         out << "\t"; 
      }
  };
  class NLFormatItem : public FormatItem 
  {
    public:
      void format(std::ostream &out, const LogMsg &msg) override
      {
         out << "\n"; 
      }
  };
  class OtherFormatItem : public FormatItem 
  {
    public:
      OtherFormatItem(const std::string &str)
        :_str(str)
      {}
      void format(std::ostream &out, const LogMsg &msg) override
      {
         out << _str; 
      }
    private:
      std::string _str;
  };
  
  class Formatter 
  {
    public:
      using ptr = std::shared_ptr<Formatter>;
      Formatter(const std::string &pattern = "[%d{%H:%M:%S}][%t][%c][%f:%l][%p]%T%m%n")
        :_pattern(pattern)
        {
          assert(parsePattern());//格式化规则字符串的解析必须成功
        }
      // 对msg进行格式化
      void format(std::ostream &out,LogMsg &msg)
      {
        for(auto &item : _items)
        {
          item->format(out,msg);
        }
      }
      std::string format(LogMsg &msg)
      {
        std::stringstream ss;
        format(ss,msg);
        return ss.str();
      }
    private:
      // 对格式化规则字符串进行解析
      bool parsePattern()
      {
        // 1.对格式化规则字符串进行解析
        std::vector<std::pair<std::string, std::string>> fmt_order;
        size_t pos = 0;
        std::string key,val;
        while(pos < _pattern.size())
        {
          // 1.处理原始字符串--判断是否是%，不是就是原始字符
          if(_pattern[pos] != '%')
          {
            val.push_back(_pattern[pos++]);
            continue;
          }
          // 代表pos位置就是%字符，防止%%代表为一个原始%字符
          if(pos +1 <_pattern.size()&&_pattern[pos + 1] == '%')
          {
            val.push_back('%');
            pos += 2;
            continue;
          }
          // 代表%后面是格式化字符，代表原始字符串处理完毕
          if(val.empty() == false)
          {
            fmt_order.push_back(std::make_pair("",val));
            val.clear();
          }

          // 此时pos指向位置是%所在位置
          // 开始格式化字符串的处理
          pos += 1; //pos指向格式化字符的位置
          if(pos == _pattern.size())
          {
            std::cout << "%之后，没有对应的格式化字符！\n";
            return false;
          }
          key = _pattern[pos];
          pos += 1;//pos指向格式化字符串后一个位置
          if(pos < _pattern.size() && _pattern[pos] == '{')
          {
            pos += 1;// pos指向了子规则的起始位置
            while(pos < _pattern.size() && _pattern[pos] != '}')
            {
              val.push_back(_pattern[pos++]);
            }
            // 若走到最后末尾退出循环，则表示无'}'表示格式化字符串出错
            if(pos == _pattern.size())
            {
              std::cout << "子规则{}匹配出错！\n";
              return false;
            }
            pos += 1; //需要让pos指向'}'字符的下一个位置继续开始循环
          }
          // 将子规则的key 和 value 字符串添加到，fmt_order数组中
          fmt_order.push_back(std::make_pair(key,val));
          key.clear();
          val.clear();
        }
        // 2.根据解析得到的数据初始化格式化子项数组成员
        for(auto &it : fmt_order)
        {
          _items.push_back(createItem(it.first,it.second));
        }  
        return true;
      }
      //根据不同的格式化字符创建不同的格式化子项对象
      FormatItem::ptr createItem(const std::string &key,const std::string &val)
      {
        if(key == "d") return std::make_shared<TimeFormatItem>(val);
        if(key == "t") return std::make_shared<ThreadFormatItem>();
        if(key == "c") return std::make_shared<LoggerFormatItem>();
        if(key == "f") return std::make_shared<FileFormatItem>();
        if(key == "l") return std::make_shared<LineFormatItem>();
        if(key == "p") return std::make_shared<LevelFormatItem>();
        if(key == "T") return std::make_shared<TabFormatItem>();
        if(key == "m") return std::make_shared<MsgFormatItem>();
        if(key == "n") return std::make_shared<NLFormatItem>();
        if(key == "") return std::make_shared<OtherFormatItem>(val);
        std::cout << "没有对应的格式化字符：%" << key << std::endl;
        abort();
        return FormatItem::ptr();// 返回空的智能指针
      }
    private:
      std::string _pattern;//格式化规则字符串
      std::vector<FormatItem::ptr> _items;
  };
  
  
}
#endif 
